import { DoublyNode } from './models'
import LinkedList from './linkedlist'

class DoublyLinkedList extends LinkedList {
  constructor () {
    super()
    this.tail = null // 补充一个尾结点地址
  }

  push (element) {
    const node = new DoublyNode(element)
    if (this.head === null) {
      this.head = node
      this.tail = node
    } else {
      this.tail.next = node
      node.prev = this.tail
      this.tail = node
    }
    this.count++
  }

  insert (element, index) {
    if (index > this.count || index < 0) {
      throw new Error('target index out of range:' + this.count)
    }
    const node = new DoublyNode(element)
    // 头插
    if (index === 0) {
      // 链表为空
      if (this.head === null) {
        this.head = node
      } else {
        node.next = this.head
        this.head.prev = node
        this.head = node
      }
      this.count++
    } else if (index === this.count) {
      this.push(element)
    } else {
      const p = this.getElementAt(index)
      node.next = p
      node.prev = p.prev
      p.prev.next = node
      p.prev = node
      this.count++
    }
  }

  removeAt (index) {
    if (index >= this.count || index < 0) {
      throw new Error('target index out of range:' + this.count)
    }
    const target = this.getElementAt(index)
    // 头部
    if (index === 0) {
      this.head = target.next
      target.next.prev = null
    } else if (index === this.count - 1) {
      // 尾部
      this.tail = target.prev
      target.prev.next = null
    } else {
      // 中间
      target.prev.next = target.next
      target.next.prev = target.prev
    }
    target.next = null
    target.prev = null
    this.count--
    return target
  }

  toString () {
    let result = ''
    for (let p = this.head; p !== null; p = p.next) {
      result += `${p.element}<>`
    }
    result += 'null'
    return result
  }

  toStringInverse () {
    let result = ''
    for (let p = this.tail; p !== null; p = p.prev) {
      result += `${p.element}<>`
    }
    result += 'head'
    return result
  }
}

export default DoublyLinkedList
